
import java.net.MalformedURLException;
import java.net.URL;
import java.util.Hashtable;
import java.util.Stack;

import javax.swing.text.MutableAttributeSet;
import javax.swing.text.html.HTML;
import javax.swing.text.html.HTMLEditorKit;

/**
 * Overrides the three methods handleStartTag, handleEndTag, and handleText.
 * The new functionality is such that the relevant text is indexed while its
 * being parsed. This allows subsequent lookups on keywords to correlate those
 * search queries to relevant web pages.
 * @author alrik firl (afirl)
 * @author Pin-Wei Cheng (picheng)
 */
public class CallbackParser extends HTMLEditorKit.ParserCallback {
	private String currentURL;
	private Hashtable<String, Hashtable<String, Integer>> hashtable;
	private Hashtable<String, Integer> hashtableValue;
	private String href;
	private boolean openedAHREF;
	private int totalDistinctKeywordsCount;
	private Stack<String> adjacentURLs;
	private Stack<String> distinctKeywords;
	// private boolean workingURL;
	private boolean lastURL;

	/**
	 * returns the number of distinct keywords at a point in time
	 * 
	 * @return the distinctKeywordsCount
	 */
	public int getDistinctKeywordsCount() {
		return distinctKeywords.size();
	}

	/**
	 * Accessor method for getting the number of distinct keywords
	 * 
	 * @return the totalDistinctKeywordsCount
	 */
	public int getTotalDistinctKeywordsCount() {
		return totalDistinctKeywordsCount;
	}

	public CallbackParser(String currentURL,
			Hashtable<String, Hashtable<String, Integer>> hashtable) {
		this.currentURL = currentURL;
		this.hashtable = hashtable;
		hashtable = new Hashtable<String, Hashtable<String, Integer>>();
		openedAHREF = false;
		totalDistinctKeywordsCount = 0;
		adjacentURLs = new Stack<String>();
		distinctKeywords = new Stack<String>();
		// workingURL = true;
		lastURL = false;
	}

	/**
	 * sets the last URL that was visited
	 * 
	 * @param lastURL
	 *            the lastURL to set
	 */
	public void setLastURL(boolean lastURL) {
		this.lastURL = lastURL;
	}

	/**
	 * accessor methods to obtain a URL's adjacency list
	 * 
	 * @return the adjacentURL
	 */
	public Stack<String> getAdjacentURLs() {
		// System.out.println("<<<IN CALLBACK PARSER>>> "+this.adjacentURLs);
		return adjacentURLs;

	}

	/**
	 * Setter method for populating a URL's adjacency list
	 * 
	 * @param adjacentURL
	 *            the adjacentURL to set
	 */
	public void setAdjacentURLs(Stack<String> adjacentURL) {
		this.adjacentURLs = adjacentURL;

	}

	/**
	 * Accessor method for obtaining the Indexing hashtable
	 * 
	 * @return the hashtable
	 */
	public Hashtable<String, Hashtable<String, Integer>> getHashtable() {
		return hashtable;
	}

	/**
	 * Setter method, populates the centralized indexing hashtable
	 * 
	 * @param hashtable
	 *            the hashtable to set
	 */
	public void setHashtable(
			Hashtable<String, Hashtable<String, Integer>> hashtable) {
		this.hashtable = hashtable;
	}

	/**
	 * @inheritDoc Parses the URLs and their HREF attributes. Adds new URLs to
	 * the current URL's adjacency list, and
	 */
	public void handleStartTag(HTML.Tag tag, MutableAttributeSet attr, int pos) {

		if (tag == HTML.Tag.A) {
			/* The string representation of the attributes */
			Object object = attr.getAttribute(HTML.Attribute.HREF);

			if (object != null) {

				try {
					openedAHREF = true;
					URL currentURLURL = new URL(currentURL);
					URL url = new URL(currentURLURL, (String) object);
					href = url.toExternalForm();

					adjacentURLs.push(href);

				} catch (MalformedURLException e) {
					// URL myURL = new URL(currentURL,"assignments.html");

					e.printStackTrace();
					// } catch (FileNotFoundException e){
					// workingURL = false;
					// System.out.print("Found unworking url.");
					// } catch(IOException e){
					//					
				}
			} /*else {
				System.out.println("Anchor tag without href attribute.");
			}*/
		}
	}

	/**
	 * @inheritDoc Marks that the URL corresponding to the current anchor tag
	 * is now closed
	 */
	public void handleEndTag(HTML.Tag tag, int pos) {

		if (tag == HTML.Tag.A) {
			openedAHREF = false;
			// if its an end tag, is this enough of a check? Have to check for
			// the /?
		}
	}

	/**
	 * @inheritDoc handleText, as the name implies, is invoked when any
	 * content is encountered in the document. The text and location (as an
	 * integer into the document) are passed in.
	 * 
	 * Each occurrence of white space (any newlines, tabs, carriage returns, or
	 * multiple spaces) is coalesced into a single space character.
	 */
	public void handleText(char[] text, int pos) {

		String[] string = new String(text).split("\\W");

		for (String nextToken : string) {
			// nextToken = st.next();
			// System.out.println(nextToken + "  ");
			nextToken = Keyword.makeKeyword(nextToken);

			// System.out.println("stem into " + nextToken + "  ");

			/* check if token is a stop word */
			if (!nextToken.equals("")) {// System.out.println(" (not stop) \n");

				if (!distinctKeywords.contains(nextToken)) {
					// System.out.println("adding  " + nextToken);
					distinctKeywords.push(nextToken);
				}

				/* check if keyword already exist */
				if (hashtable.containsKey(nextToken)) {
					hashtableValue = hashtable.get(nextToken);
					/* currently in a href tag */
					if (openedAHREF && !lastURL) {// System.out.println("#####");
						/* keyword contains a href url */
						if (hashtableValue.containsKey(href)) {
							int tempInt = hashtableValue.get(href);
							hashtableValue.put(href, ++tempInt);
						}
						/* keyword does not contain a href url */
						else {
							hashtableValue.put(href, 1);
							// adjacentURLs.push(href);
						}
					}
					/* currently not in a href tag */
					// else{
					/* keyword contains current url */
					if (hashtableValue.containsKey(currentURL)) {
						int tempInt = hashtableValue.get(currentURL);
						hashtableValue.put(currentURL, ++tempInt);
					}
					/* keyword does not contain current url */
					else {
						hashtableValue.put(currentURL, 1);
					}
				}
				/* keyword not in hashtable */
				else {
					Hashtable<String, Integer> tempHashtable = new Hashtable<String, Integer>();

					if (openedAHREF && !lastURL) {// System.out.println("#####");
						tempHashtable.put(href, 1);

						// adjacentURLs.push(href);// push adjacent urls
					}
					tempHashtable.put(currentURL, 1);
					hashtable.put(nextToken, tempHashtable);
					// System.out.println(nextToken);
					totalDistinctKeywordsCount++;

				}
			}

		}
	}

}
